iT邦幫忙

2024 iThome 鐵人賽

DAY 6
0

每天的專案會同步到 GitLab 上,可以前往 GitLab 查看。
有興趣的朋友歡迎留言 or 來信討論,我的信箱是 nickchen1998@gmail.com

昨天介紹了如何客製化一個自己的 Tool,今天我們來看一下 LangChain 內建的 Tool,
如同標題所述,今天我們挑選的 Tool 就是 QuerySQLDataBaseTool,這個 Tool 可以協助我們針對資料庫進行一些操作。

建立資料表

首先我們要先建立一個資料表,這邊我們使用 SQLite 作為範例,並且建立兩張資料表,分別是 Items 以及 Orders:

下方的程式碼是使用 SQLAlchemy 2.0 來進行開發的,針對這點不熟的朋友,可以參考 官方文件 來了解如何使用 SQLAlchemy 2.0。

from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship

Base = declarative_base()


class Order(Base):
    __tablename__ = 'orders'

    id = Column(Integer, primary_key=True, index=True)
    customer_name = Column(String, index=True)
    items = relationship("Item", back_populates="order")


class Item(Base):
    __tablename__ = 'items'

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)
    quantity = Column(Integer)
    order_id = Column(Integer, ForeignKey('orders.id'))
    order = relationship("Order", back_populates="items")


def main():
    engine = create_engine("sqlite:///./test.db", echo=True)
    session = sessionmaker(autocommit=False, autoflush=False, bind=engine)()
    Base.metadata.drop_all(bind=engine)
    Base.metadata.create_all(bind=engine)

    order1 = Order(customer_name="Alice")
    order1.items = [
        Item(name="Latte", quantity=1),
        Item(name="Cappuccino", quantity=2)
    ]

    order2 = Order(customer_name="Bob")
    order2.items = [
        Item(name="Espresso", quantity=1),
        Item(name="Mocha", quantity=1)
    ]

    session.add_all([order1, order2])
    session.commit()

    session.close()


if __name__ == "__main__":
    main()

直接執行上面這段程式碼,應該可以看到你的目錄當中出現了一個 test.db 這個 sqlite 資料庫檔,
並且裡面會有如下圖中的兩張資料表以及一些資料。

table and datas

串接 LangChain 與資料庫

我們可以透過 QuerySQLDataBaseTool 來進行資料庫的操作,這個 Tool 會將 SQL 語句傳遞給資料庫進行操作,
這個物件當中需要接收一個名為 db 的參數,型態為 SQLDatabase,這個參數是用來設定你要連到哪個資料庫,可以參考下方的範例:

from env_settings import EnvSettings
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from langchain_community.tools import QuerySQLDataBaseTool
from langchain_community.utilities import SQLDatabase


env_settings = EnvSettings()
llm = ChatOpenAI(
    api_key=env_settings.OPENAI_API_KEY,
    model_name="gpt-4o"
)

db = SQLDatabase.from_uri("sqlite:///./test.db")
tools = [QuerySQLDataBaseTool(db=db)]
llm = llm.bind_tools(tools)

messages = [HumanMessage(content="請問現在有幾張訂單?")]
ai_message = llm.invoke(messages)
print(ai_message.tool_calls)

可以看到在範例當中,我們將 QuerySQLDataBaseTool 這個 Tool 傳入 tools 這個列表當中,並且透過 SQLDatabase 來設定我們要連接的資料庫,
下圖中可以看到 GPT 成功針對我們的問題選擇了指定的 Tool 並且產生了指定的 SQL 語句:

tool call

彙整進語言模型

在確認他可以自動讀取到我們的資料表並產生 SQL 語句後,我們就趕緊把這個 Tool 的流程串起來,下方是完整的程式碼:

from env_settings import EnvSettings
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, ToolMessage
from langchain_community.tools import QuerySQLDataBaseTool
from langchain_community.utilities import SQLDatabase


env_settings = EnvSettings()
llm = ChatOpenAI(
    api_key=env_settings.OPENAI_API_KEY,
    model_name="gpt-4o"
)

db = SQLDatabase.from_uri("sqlite:///./test.db")
tools = [QuerySQLDataBaseTool(db=db)]
llm = llm.bind_tools(tools)

messages = [HumanMessage(content="請問現在有幾張訂單?")]
ai_message = llm.invoke(messages)

tool_messages = []
for tool_call in ai_message.tool_calls:
    for tool in tools:
        if tool_call.get("name") == tool.name:
            tool_content = tool.run(tool_call.get("args"))
            print(f"tool content: {tool_content}")
            tool_messages.append(ToolMessage(
                content=tool_content,
                tool_call_id=tool_call.get("id"),
            ))
            break

messages.append(ai_message)
messages.extend(tool_messages)

ai_message = llm.invoke(messages)
print(f"ai content: {ai_message.content}")

在範例中可以看到,我們把 tool content 以及 ai content 印出來(如下圖),方便我們查看查詢出的資料是否正確以及回答的內容,可以看到查出來以及
GPT 的回答都是正確的。

tool result

內容預告

今天我們介紹了該如何使用 QuerySQLDataBaseTool 這個 Tool 來進行資料庫的操作,然而應該有朋友會發現,當你的資料表更加複雜時,
會慢慢地出現錯誤的 SQL 語句,如下圖中我們把問題換成複雜一點,可以看到他產生了跟我們設計的資料表不符的 SQL 語法

tool fail

那是因為 QuerySQLDataBaseTool 其實本質上只是個用來 執行 SQL 的一個 Tool,
明天我們將要介紹一下在 LangChain 當中獨特的鍊式語言 Chain,將資料表資訊整合進整個查詢的過程當中。


上一篇
Day 05 - Function Call (Tool)
下一篇
Day 07 - LangChain 中的 Chain
系列文
初探 Langchain 與 LLM:打造簡易問診機器人13
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言